#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>

#define SERVER_PORT 8888
#define BACKLOG 10
#define MAX_BUFF_LEN 101
int main(int argc, char *argv[]){
	int sockfd, newfd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int sin_size;
	char buff[MAX_BUFF_LEN];

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
		printf("socket error\n");
		exit(1);
	}
	int opt=1;
	int len = sizeof(opt);
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, &len);
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVER_PORT);
	server_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(server_addr.sin_zero), 8);

	if(bind(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr)) == -1){
		printf("bind error\n");
		exit(1);
	}

	if(listen(sockfd, BACKLOG) == -1){
		printf("listen error\n");
		exit(1);
	}

	while(1){
		int reclen;
		sin_size =sizeof(struct sockaddr_in);
		if((newfd = accept(sockfd, (struct sockaddr*)(&client_addr), &sin_size)) == -1){
			printf("accept error\n");
			continue;
		}
		int opt=1;
		int len = sizeof(opt);
		setsockopt(newfd, SOL_SOCKET, SO_REUSEADDR, &opt, &len);
		printf("server:got connection from %s\n", inet_ntoa(client_addr.sin_addr));

		if(!fork()){
			int closing = 0;
			while(!closing){
				if((reclen = recv(newfd, buff, MAX_BUFF_LEN-1, 0)) == -1){
					printf("receive error\n");
					exit(1);
				}
				if((reclen == 0) || (buff[0] == '!' && buff[1] == 'q')){
					printf("closing the socket.....\n");
					closing = 1;
					close(newfd);
					break;
				}
				printf("receive bytes:%d\n", reclen);
				buff[reclen] = '\0';
				write(STDOUT_FILENO, buff, reclen);
				if(send(newfd, buff, strlen(buff), 0) == -1){
					printf("send error\n");
					exit(1);
				}
			}
			close(newfd);
		}
	}
	while(waitpid(-1, NULL, WNOHANG) > 0);
}
